/**
 * 通用工具函数
 */

/**
 * 格式化文件大小
 * @param {number} bytes - 文件大小（字节）
 * @param {number} decimals - 小数位数
 * @returns {string} 格式化后的文件大小
 */
export function formatFileSize(bytes, decimals = 2)
{
  if (bytes === 0) return '0 B'

  const k = 1024
  const dm = decimals < 0 ? 0 : decimals
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']

  const i = Math.floor(Math.log(bytes) / Math.log(k))

  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
}

/**
 * 格式化数字，添加千分位分隔符
 * @param {number} num - 要格式化的数字
 * @returns {string} 格式化后的数字字符串
 */
export function formatNumber(num)
{
  if (num === null || num === undefined) return '0'
  return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}

/**
 * 防抖函数
 * @param {Function} func - 要防抖的函数
 * @param {number} wait - 等待时间（毫秒）
 * @param {boolean} immediate - 是否立即执行
 * @returns {Function} 防抖后的函数
 */
export function debounce(func, wait, immediate = false)
{
  let timeout
  return function (...args)
  {
    const later = () =>
    {
      timeout = null
      if (!immediate) func.apply(this, args)
    }
    const callNow = immediate && !timeout
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
    if (callNow) func.apply(this, args)
  }
}

/**
 * 节流函数
 * @param {Function} func - 要节流的函数
 * @param {number} wait - 等待时间（毫秒）
 * @returns {Function} 节流后的函数
 */
export function throttle(func, wait)
{
  let timeout
  return function (...args)
  {
    if (!timeout)
    {
      func.apply(this, args)
      timeout = setTimeout(() =>
      {
        timeout = null
      }, wait)
    }
  }
}

/**
 * 深拷贝对象
 * @param {any} obj - 要拷贝的对象
 * @returns {any} 拷贝后的对象
 */
export function deepClone(obj)
{
  if (obj === null || typeof obj !== 'object') return obj
  if (obj instanceof Date) return new Date(obj.getTime())
  if (obj instanceof Array) return obj.map(item => deepClone(item))

  const cloned = {}
  for (const key in obj)
  {
    if (obj.hasOwnProperty(key))
    {
      cloned[key] = deepClone(obj[key])
    }
  }
  return cloned
}

/**
 * 检查是否为空值
 * @param {any} value - 要检查的值
 * @returns {boolean} 是否为空
 */
export function isEmpty(value)
{
  if (value === null || value === undefined) return true
  if (typeof value === 'string') return value.trim() === ''
  if (Array.isArray(value)) return value.length === 0
  if (typeof value === 'object') return Object.keys(value).length === 0
  return false
}

/**
 * 生成随机ID
 * @param {number} length - ID长度
 * @returns {string} 随机ID
 */
export function generateId(length = 8)
{
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let result = ''
  for (let i = 0; i < length; i++)
  {
    result += chars.charAt(Math.floor(Math.random() * chars.length))
  }
  return result
}

/**
 * 获取URL参数
 * @param {string} name - 参数名
 * @param {string} url - URL字符串，默认为当前页面URL
 * @returns {string|null} 参数值
 */
export function getUrlParam(name, url = window.location.href)
{
  const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)')
  const results = regex.exec(url)
  if (!results) return null
  if (!results[2]) return ''
  return decodeURIComponent(results[2].replace(/\+/g, ' '))
}

/**
 * 设置URL参数
 * @param {string} name - 参数名
 * @param {string} value - 参数值
 * @param {string} url - URL字符串，默认为当前页面URL
 * @returns {string} 新的URL
 */
export function setUrlParam(name, value, url = window.location.href)
{
  const regex = new RegExp('([?&])' + name + '=.*?(&|$)', 'i')
  const separator = url.indexOf('?') !== -1 ? '&' : '?'

  if (url.match(regex))
  {
    return url.replace(regex, '$1' + name + '=' + value + '$2')
  } else
  {
    return url + separator + name + '=' + value
  }
}

/**
 * 下载文件
 * @param {string} content - 文件内容
 * @param {string} filename - 文件名
 * @param {string} mimeType - MIME类型
 */
export function downloadFile(content, filename, mimeType = 'text/plain')
{
  const blob = new Blob([content], { type: mimeType })
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = filename
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  URL.revokeObjectURL(url)
}

/**
 * 复制文本到剪贴板
 * @param {string} text - 要复制的文本
 * @returns {Promise<boolean>} 是否复制成功
 */
export async function copyToClipboard(text)
{
  try
  {
    await navigator.clipboard.writeText(text)
    return true
  } catch (error)
  {
    // 降级方案
    try
    {
      const textArea = document.createElement('textarea')
      textArea.value = text
      textArea.style.position = 'fixed'
      textArea.style.left = '-9999px'
      document.body.appendChild(textArea)
      textArea.select()
      document.execCommand('copy')
      document.body.removeChild(textArea)
      return true
    } catch (fallbackError)
    {
      console.error('复制失败:', fallbackError)
      return false
    }
  }
}

/**
 * 格式化时间
 * @param {Date|string|number} date - 日期
 * @param {string} format - 格式字符串
 * @returns {string} 格式化后的时间字符串
 */
export function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss')
{
  const d = new Date(date)
  if (isNaN(d.getTime())) return ''

  const year = d.getFullYear()
  const month = String(d.getMonth() + 1).padStart(2, '0')
  const day = String(d.getDate()).padStart(2, '0')
  const hour = String(d.getHours()).padStart(2, '0')
  const minute = String(d.getMinutes()).padStart(2, '0')
  const second = String(d.getSeconds()).padStart(2, '0')

  return format
    .replace('YYYY', year)
    .replace('MM', month)
    .replace('DD', day)
    .replace('HH', hour)
    .replace('mm', minute)
    .replace('ss', second)
}

/**
 * 计算相对时间
 * @param {Date|string|number} date - 日期
 * @returns {string} 相对时间描述
 */
export function timeAgo(date)
{
  const now = new Date()
  const target = new Date(date)
  const diff = now.getTime() - target.getTime()

  if (diff < 60000) return '刚刚'
  if (diff < 3600000) return Math.floor(diff / 60000) + '分钟前'
  if (diff < 86400000) return Math.floor(diff / 3600000) + '小时前'
  if (diff < 2592000000) return Math.floor(diff / 86400000) + '天前'
  if (diff < 31536000000) return Math.floor(diff / 2592000000) + '个月前'
  return Math.floor(diff / 31536000000) + '年前'
}

/**
 * 验证邮箱格式
 * @param {string} email - 邮箱地址
 * @returns {boolean} 是否为有效邮箱
 */
export function isValidEmail(email)
{
  const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  return regex.test(email)
}

/**
 * 验证手机号格式
 * @param {string} phone - 手机号
 * @returns {boolean} 是否为有效手机号
 */
export function isValidPhone(phone)
{
  const regex = /^1[3-9]\d{9}$/
  return regex.test(phone)
}

/**
 * 获取浏览器信息
 * @returns {object} 浏览器信息
 */
export function getBrowserInfo()
{
  const ua = navigator.userAgent
  const browser = {
    name: 'Unknown',
    version: 'Unknown',
    os: 'Unknown'
  }

  // 检测浏览器
  if (ua.includes('Chrome') && !ua.includes('Edge'))
  {
    browser.name = 'Chrome'
    browser.version = ua.match(/Chrome\/([0-9.]+)/)?.[1] || 'Unknown'
  } else if (ua.includes('Firefox'))
  {
    browser.name = 'Firefox'
    browser.version = ua.match(/Firefox\/([0-9.]+)/)?.[1] || 'Unknown'
  } else if (ua.includes('Safari') && !ua.includes('Chrome'))
  {
    browser.name = 'Safari'
    browser.version = ua.match(/Version\/([0-9.]+)/)?.[1] || 'Unknown'
  } else if (ua.includes('Edge'))
  {
    browser.name = 'Edge'
    browser.version = ua.match(/Edge\/([0-9.]+)/)?.[1] || 'Unknown'
  }

  // 检测操作系统
  if (ua.includes('Windows'))
  {
    browser.os = 'Windows'
  } else if (ua.includes('Mac OS'))
  {
    browser.os = 'macOS'
  } else if (ua.includes('Linux'))
  {
    browser.os = 'Linux'
  } else if (ua.includes('Android'))
  {
    browser.os = 'Android'
  } else if (ua.includes('iOS'))
  {
    browser.os = 'iOS'
  }

  return browser
}

/**
 * 存储操作封装
 */
export const storage = {
  // localStorage 操作
  local: {
    set(key, value)
    {
      try
      {
        localStorage.setItem(key, JSON.stringify(value))
        return true
      } catch (error)
      {
        console.error('localStorage set error:', error)
        return false
      }
    },
    get(key, defaultValue = null)
    {
      try
      {
        const item = localStorage.getItem(key)
        return item ? JSON.parse(item) : defaultValue
      } catch (error)
      {
        console.error('localStorage get error:', error)
        return defaultValue
      }
    },
    remove(key)
    {
      try
      {
        localStorage.removeItem(key)
        return true
      } catch (error)
      {
        console.error('localStorage remove error:', error)
        return false
      }
    },
    clear()
    {
      try
      {
        localStorage.clear()
        return true
      } catch (error)
      {
        console.error('localStorage clear error:', error)
        return false
      }
    }
  },

  // sessionStorage 操作
  session: {
    set(key, value)
    {
      try
      {
        sessionStorage.setItem(key, JSON.stringify(value))
        return true
      } catch (error)
      {
        console.error('sessionStorage set error:', error)
        return false
      }
    },
    get(key, defaultValue = null)
    {
      try
      {
        const item = sessionStorage.getItem(key)
        return item ? JSON.parse(item) : defaultValue
      } catch (error)
      {
        console.error('sessionStorage get error:', error)
        return defaultValue
      }
    },
    remove(key)
    {
      try
      {
        sessionStorage.removeItem(key)
        return true
      } catch (error)
      {
        console.error('sessionStorage remove error:', error)
        return false
      }
    },
    clear()
    {
      try
      {
        sessionStorage.clear()
        return true
      } catch (error)
      {
        console.error('sessionStorage clear error:', error)
        return false
      }
    }
  }
}
